package com.banzhang.gameAI.Astar;


import java.awt.*;
import java.util.LinkedList;

public class AStar {

    private LinkedList<AStarStruct> openList;
    private LinkedList<AStarStruct> closeList;


    void start() {
        openList = new LinkedList<AStarStruct>();
        closeList = new LinkedList<AStarStruct>();

    }
    private int count = 0;




    public void AStartest() {
        start();
        AStarStruct startPoint= new AStarStruct();
        AStarStruct endPoint= new AStarStruct();

        setStartAndEndPoint(startPoint, endPoint);

        openList.add(startPoint);
        while (getGValue(startPoint.getX(), startPoint.getY(), endPoint.getX(), endPoint.getY()) != 0) {
            count++;
            System.out.println("count:" + count);
            if (startPoint.getX() + 1 < AStarMap.map[0].length && AStarMap.map[startPoint.getY()][startPoint.getX() + 1] == 1 &&
                    notInCloseList(startPoint.getX() + 1, startPoint.getY())
                    && notInOpenList(startPoint.getX() + 1, startPoint.getY())) {
                AStarStruct tempPoint = getaStarStruct(startPoint, endPoint, startPoint.getX() + 1, startPoint.getY());
                openList.add(tempPoint);
                System.out.println("[startPoint.getY()][startPoint.getX()+1]");
            }
            if (startPoint.getX() - 1 >= 0 && AStarMap.map[startPoint.getY()][startPoint.getX() - 1] == 1 &&
                    notInCloseList(startPoint.getX() - 1, startPoint.getY())
                    && notInOpenList(startPoint.getX() - 1, startPoint.getY())) {
                AStarStruct tempPoint = getaStarStruct(startPoint, endPoint, startPoint.getX() - 1, startPoint.getY());
                openList.add(tempPoint);
                System.out.println("[startPoint.getY()][startPoint.getX()-1]");
            }
            if (startPoint.getY() + 1 < AStarMap.map.length && AStarMap.map[startPoint.getY() + 1][startPoint.getX()] == 1 &&
                    notInCloseList(startPoint.getX(), startPoint.getY() + 1)
                    && notInOpenList(startPoint.getX(), startPoint.getY() + 1)) {
                AStarStruct tempPoint = getaStarStruct(startPoint, endPoint, startPoint.getX(), startPoint.getY() + 1);
                openList.add(tempPoint);
                System.out.println("[startPoint.getY()+1][startPoint.getX()]");
            }
            if (startPoint.getY() - 1 >= 0 && AStarMap.map[startPoint.getY() - 1][startPoint.getX()] == 1 &&
                    notInCloseList(startPoint.getX(), startPoint.getY() - 1)
                    && notInOpenList(startPoint.getX(), startPoint.getY() - 1)) {
                AStarStruct tempPoint = getaStarStruct(startPoint, endPoint, startPoint.getX(), startPoint.getY() - 1);
                openList.add(tempPoint);
                System.out.println("[startPoint.getY()-1][startPoint.getX()]");
            }
            closeList.add(startPoint);

            openList.remove(startPoint);
/*            for (int i = 0; i < openList.size(); i++) {
                if (openList.get(i).equals(startPoint)) {
                    System.out.println("openList.remove:" + i + openList.get(i).toString());
                    openList.remove(i);
                }
            }*/

            startPoint = getNewStartPoint(startPoint);
            System.out.println(startPoint.toString());
        }

        for (int i = 0; i < openList.size(); i++) {
            System.out.println("openList" + openList.get(i).toString());
        }
        int getListID = 0;
        AStarStruct getStarStruct = null;
        for (int i = 0; i < closeList.size(); i++) {
            if (getListID == 0) {
                getListID++;
                getStarStruct = closeList.get(i);
                System.out.println("closeList" + closeList.get(i).toString());
            } else if (closeList.get(i).getH() == getListID && closeList.get(i).getParentPoint().x == getStarStruct.getX()
                    && closeList.get(i).getParentPoint().y == getStarStruct.getY()) {
                getListID++;
                getStarStruct = closeList.get(i);
                System.out.println("closeList" + closeList.get(i).toString());
            }

        }

        System.out.println("###################################");
        while (startPoint.getF() >= 1) {
            for (int i = 0; i < closeList.size(); i++) {
                if (startPoint.getF() >= 1) {
                    if (closeList.get(i).getX() == startPoint.getParentPoint().getX() &&
                            closeList.get(i).getY() == startPoint.getParentPoint().getY()) {

                        startPoint = closeList.get(i);
                        System.out.println("openList" + startPoint.toString());
                    }
                }
            }
        }
        System.out.println("###################################");
    }

    private AStarStruct getNewStartPoint(AStarStruct startPoint) {
        int tempf =Integer.MAX_VALUE ;
        for (int i = 0; i < openList.size(); i++) {

            if (openList.get(i).getF() < tempf) {
                tempf = openList.get(i).getF();
                startPoint = openList.get(i);
                System.out.println("tempf:" + tempf);
            }

        }
        return startPoint;
    }

    private void setStartAndEndPoint(AStarStruct startPoint, AStarStruct endPoint) {
        startPoint.setX(1);
        startPoint.setY(3);
        startPoint.setH(0);
        startPoint.setParentPoint(null);
        endPoint.setX(5);
        endPoint.setY(4);
    }

    private AStarStruct getaStarStruct(AStarStruct startPoint, AStarStruct endPoint, int x, int y) {
        AStarStruct tempPoint = new AStarStruct();
        tempPoint.setX(x);
        tempPoint.setY(y);
        tempPoint.setH(startPoint.getH() + 1);
        tempPoint.setParentPoint(new Point(startPoint.getX(), startPoint.getY()));
        tempPoint.setG(getGValue(tempPoint.getX(), tempPoint.getY(), endPoint.getX(), endPoint.getY()));
        tempPoint.setF(tempPoint.getH() + tempPoint.getG());
        return tempPoint;
    }



    private int getGValue(int startX, int startY, int endX, int endY) {
        return Math.abs(endX - startX) + Math.abs(endY - startY);
    }

    private boolean notInCloseList(int jugeX, int jugeY) {
        boolean notInCloseList = true;
        for (int i = 0; i < closeList.size(); i++) {
            if (closeList.get(i).getX() == jugeX && closeList.get(i).getY() == jugeY) {
                notInCloseList = false;
            }
        }
        return notInCloseList;
    }

    private boolean notInOpenList(int jugeX, int jugeY) {
        boolean notInCloseList = true;
        for (int i = 0; i < openList.size(); i++) {
            if (openList.get(i).getX() == jugeX && openList.get(i).getY() == jugeY) {
                notInCloseList = false;
            }
        }
        return notInCloseList;
    }
}
